package sipus.action.master.helper;

import java.io.Serializable;
import java.util.Date;
import java.util.List;

import org.hibernate.EntityMode;
import org.hibernate.Session;
import org.hibernate.criterion.Restrictions;
import org.hibernate.envers.AuditReader;
import org.hibernate.envers.AuditReaderFactory;
import org.hibernate.envers.query.AuditEntity;
import org.hibernate.envers.query.AuditQuery;
import org.hibernate.metadata.ClassMetadata;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zk.ui.sys.ExecutionsCtrl;
import org.zkoss.zul.A;
import org.zkoss.zul.Borderlayout;
import org.zkoss.zul.Caption;
import org.zkoss.zul.Center;
import org.zkoss.zul.Column;
import org.zkoss.zul.Columns;
import org.zkoss.zul.Detail;
import org.zkoss.zul.Grid;
import org.zkoss.zul.Groupbox;
import org.zkoss.zul.Html;
import org.zkoss.zul.Label;
import org.zkoss.zul.ListModel;
import org.zkoss.zul.Messagebox;
import org.zkoss.zul.Panel;
import org.zkoss.zul.Panelchildren;
import org.zkoss.zul.Row;
import org.zkoss.zul.RowRenderer;
import org.zkoss.zul.Rows;
import org.zkoss.zul.SimpleListModel;
import org.zkoss.zul.South;
import org.zkoss.zul.Toolbar;
import org.zkoss.zul.Toolbarbutton;
import org.zkoss.zul.Window;

import sipus.common.Common;
import sipus.database.hibernate.HibernateUtil;




public class RevisiHelper extends Window {

	/**
	 * 
	 */
	private static final long serialVersionUID = 6589578552710016753L;

	private Serializable serializable;
	private Grid grid;
	private ClassMetadata classMetadata;
	private String[] columnnames;
	private Serializable entityId;
	private Class<?> myClass;

	@SuppressWarnings("rawtypes")
	public static A createNewRevisi(final Class class1,
			final Serializable serializable, String label) throws Exception {
		if (serializable == null) {
			Messagebox.show("Belum ada perubahan untuk data ini", "Informasi",
					Messagebox.OK, Messagebox.INFORMATION);
			return null;
		}
		A a = new A(label);
		a.setTooltiptext("Lihat revisi");
		a.addEventListener(Events.ON_CLICK, new EventListener() {

			@Override
			public void onEvent(Event arg0) throws Exception {
				try {
					RevisiHelper revisiHelper = new RevisiHelper(class1,
							serializable);
					ExecutionsCtrl.getCurrentCtrl().getCurrentPage()
							.getFirstRoot().appendChild(revisiHelper);
					revisiHelper.setVisible(true);
					revisiHelper.onModal();
				} catch (Exception e) {
					Messagebox.show(e.getMessage(), "Peringatan",
							Messagebox.OK, Messagebox.EXCLAMATION);
				}
			}
		});
		return a;
	}

	public RevisiHelper(Class<?> myClass, Serializable serializable)
			throws Exception {
		super();
		this.myClass = myClass;
		this.serializable = serializable;
		init();
	}

	public RevisiHelper(Class<?> myClass, Serializable serializable,
			String title, String border, boolean closable) throws Exception {
		super(title, border, closable);
		this.myClass = myClass;
		this.serializable = serializable;
		init();
	}

	class DataRenderer implements RowRenderer {

		private Session session = HibernateUtil.currentSession();

		@Override
		public void render(Row arg0, Object arg1) throws Exception {
			final Serializable serializable = (Serializable) arg1;

			try {

				Date tanggal = (Date) classMetadata.getPropertyValue(
						serializable, "tanggal_dirubah", EntityMode.POJO);
				String oleh = (String) classMetadata.getPropertyValue(
						serializable, "oleh", EntityMode.POJO);

				final Rows rows = new Rows();
				for (String property : columnnames) {
					Serializable value = (Serializable) classMetadata
							.getPropertyValue(serializable, property,
									EntityMode.POJO);
					Row row = new Row();
					row.setParent(rows);
					new Label(property).setParent(row);
					try {
						new Html((value == null ? "" : value) + "")
								.setParent(row);
					} catch (Exception e) {
						// e.printStackTrace();

						try {
							System.out.println("e.getMessage() = "
									+ e.getMessage());
							String kode = "No row with the given identifier exists: [";
							String kode1 = e.getMessage().trim()
									.substring(kode.length()).trim();
							System.out.println("kode1 = " + kode1);
							Integer index = kode1.indexOf("#");
							String namaKelas = kode1.substring(0, index);
							System.out.println("namaKelas = " + namaKelas);

							String subkode = kode1.replaceAll(namaKelas + "#",
									"").replaceAll("]", "");
							System.out.println("subkode = " + subkode);
							Serializable id = Long.parseLong(subkode.trim());
							value = (Serializable) session
									.createCriteria(namaKelas)
									.add(Restrictions.idEq(id))
									.setMaxResults(1).uniqueResult();

							new Html((value == null ? "" : value) + "")
									.setParent(row);
						} catch (Exception e1) {
							// e1.printStackTrace();
							new Label("").setParent(row);
						}
					}
				}

				final Detail detail = new Detail();
				detail.setParent(arg0);
				detail.addEventListener(Events.ON_OPEN, new EventListener() {

					@Override
					public void onEvent(Event arg0) throws Exception {
						if (detail.getChildren().size() == 0) {
							// Serializable mySerializable = (Serializable)
							// HibernateUtil
							// .currentSession().createCriteria(myClass)
							// .add(Restrictions.idEq(id))
							// .setMaxResults(1).uniqueResult();
							Groupbox groupbox = new Groupbox();
							groupbox.setParent(detail);
							groupbox.appendChild(new Caption(
									"Daftar Rincian Data"));

							Grid logUserActifityGrid = new Grid();
							logUserActifityGrid.setParent(groupbox);
							logUserActifityGrid.setWidth("100%");
							logUserActifityGrid.setHeight("100%");

							Columns columns = new Columns();

							columns.setParent(logUserActifityGrid);

							Column column = new Column();
							column.setParent(columns);
							column.setLabel("Nama Data");
							column.setWidth("15%");

							column = new Column();
							column.setParent(columns);
							column.setLabel("Isi Data");
							column.setWidth("85%");
							rows.setParent(logUserActifityGrid);
						}
					}
				});

				new Html(tanggal == null ? ""
						: Common.dateFormat3.format(tanggal)).setParent(arg0);
				new Html(oleh == null ? "" : oleh).setParent(arg0);

			} catch (Exception e2) {
				arg0.detach();
				return;
			}

		}
	}

	private void init() throws Exception {
		setTitle("Revisi untuk data " + myClass.getSimpleName());
		setWidth("95%");
		setHeight("95%");

		Panel panel = new Panel();
		panel.setParent(this);
		panel.setWidth("100%");
		panel.setHeight("100%");
		panel.setTitle("Daftar revisi untuk data " + myClass.getSimpleName());
		panel.setBorder("none");
		panel.setStyle("border:0px;");

		Panelchildren panelchildren = new Panelchildren();
		panelchildren.setParent(panel);

		Borderlayout borderlayout = new Borderlayout();
		borderlayout.setParent(panelchildren);
		Center center = new Center();
		center.setParent(borderlayout);
		center.setFlex(true);

		grid = new Grid();
		grid.setMold("paging");
		grid.setPageSize(25);
		grid.setParent(center);

		classMetadata = HibernateUtil.getClassMetadata(myClass);
		columnnames = classMetadata.getPropertyNames();
		entityId = classMetadata.getIdentifier(serializable, EntityMode.POJO);

		grid.setWidth("100%");

		Columns columns = new Columns();
		columns.setParent(grid);

		Column column = new Column();
		column.setParent(columns);
		column.setLabel("");
		column.setWidth("40px");

		column = new Column();
		column.setParent(columns);
		column.setLabel("Tanggal Dirubah");
		column = new Column();
		column.setParent(columns);
		column.setLabel("Dirubah Oleh");
		//
		// for (String property : columnnames) {
		// Column column = new Column();
		// column.setParent(columns);
		// column.setLabel(property.toUpperCase());
		// }

		South south = new South();
		south.setFlex(true);
		south.setParent(borderlayout);

		onSearchDefault(null);

		Toolbar toolbar = new Toolbar();
		toolbar.setHeight("25px");
		toolbar.setParent(south);

		Toolbarbutton button = new Toolbarbutton("Tutup", "/img/cancel.gif");
		button.setTooltiptext("Tutup");
		button.addEventListener("onClick", new EventListener() {
			@Override
			public void onEvent(Event event) throws Exception {
				detach();
			}
		});
		button.setParent(toolbar);
	}

	@SuppressWarnings("unchecked")
	public void onSearchDefault(Event event) throws Exception {
		try {
			Session session = HibernateUtil.currentSession();
			AuditReader reader = AuditReaderFactory.get(session);
			AuditQuery query = reader.createQuery().forRevisionsOfEntity(
					myClass, true, true);
			query.addOrder(AuditEntity.revisionNumber().desc());
			query.add(AuditEntity.id().eq(entityId));
			query.setMaxResults(Common.MAX_RESULT_50);

			List<Serializable> serializables = query.getResultList();
			if (serializables.size() == 0) {
				throw new Exception("Revisi tidak ditemukan");
			}
			ListModel strset = new SimpleListModel(serializables);
			grid.setRowRenderer(new DataRenderer());
			grid.setModel(strset);

			grid.renderAll();
		} catch (Exception e) {
			e.printStackTrace();
			throw new Exception("Revisi tidak ditemukan");
		}
	}
}
